; void recortar(Uint8* sprite, Uint32 numero_instancia, Uint32 ancho_instancia, Uint32 ancho_sprite, Uint32 alto_sprite, Uint8* instancia, bool orientacion);

; constantes globales

	%include "constantes.mac"

; parametros

	%define sprite							[ebp + 08]
	%define numero_instancia				[ebp + 12]
	%define ancho_instancia					[ebp + 16]
	%define ancho_sprite					[ebp + 20]
	%define alto_sprite						[ebp + 24]
	%define instancia						[ebp + 28]
	%define orientacion						[ebp + 32]

; variables

	%define ancho_sprite_bytes				[ebp - 04]
	%define ancho_instancia_bytes			[ebp - 08]
	%define resto_ancho_sprite_bytes		[ebp - 12]
	%define resto_ancho_instancia_bytes		[ebp - 16]
	%define p_fila							[ebp - 20]
	%define p_columna						[ebp - 24]
	%define p_instancia						[ebp - 28]
	%define partes							[ebp - 32]
	
; constantes

	%define bytes_en_128_bits				16
	%define pixeles_completos_en_128_bits	5
	%define bytes_en_5_pixeles				15

	%define bytes_reservados				32

global recortar

section .text

recortar:

	push ebp								; creo el marco de la pila
	mov ebp, esp							; creo el marco de la pila
	sub esp, bytes_reservados				; reservo memoria en la pila
	push ebx								; salvo registros convencion C
	push edi								; salvo registros convencion C
	push esi								; salvo registros convencion C

calculo_ancho_sprite_bytes:

	mov eax, ancho_sprite
	mov ebx, bytes_por_pixel
	mul ebx
	mov ancho_sprite_bytes, eax

calculo_resto:

	mov edx, eax
	shl edx, 30
	shr edx, 30								; edx = ancho_sprite_bytes % 4
	
	mov resto_ancho_sprite_bytes, edx
				
	cmp edx, 0
	je calcular_ancho_instancia_bytes
	
ajustar_ancho_sprite_bytes:

	mov eax, 4
	sub eax, edx							; eax = (4 - resto)
	add ancho_sprite_bytes, eax				; ancho_sprite_bytes % 4 == 0
	
calcular_ancho_instancia_bytes:

	mov eax, ancho_instancia				; eax = ancho_instancia
	mov ebx, bytes_por_pixel				; ebx = bytes_por_pixel
	mul ebx									; eax = ancho_instancia_bytes
	mov ancho_instancia_bytes, eax
	
calculo_resto_instancia:

	mov edx, eax
	shl edx, 30
	shr edx, 30								; edx = ancho_sprite_bytes % 4
					
	mov resto_ancho_instancia_bytes, edx
	
calcular_bytes_hasta_primer_columna:
	
	mov eax, ancho_instancia_bytes
	mov ebx, numero_instancia				; ebx = numero_instancia
	mul ebx									; eax = bytes_hasta_primer_columna
	
inicializar_punteros:

	mov ebx, sprite
	add eax, ebx							; eax = bytes_hasta_primer_columna + sprite
	mov p_fila, eax							; p_fila = bytes_hasta_primer_columna + sprite
	mov eax, instancia
	mov p_instancia, eax
	
calcular_partes:

	mov eax, ancho_instancia_bytes
	mov ebx, bytes_en_128_bits
	div ebx
	mov partes, eax
	
inicializar_para_cada_fila:

	mov esi, alto_sprite					; esi = contador de fila
	
para_cada_fila:

	cmp esi, 0
	je fin									; si esi = 0 termino
	
entro_fila:

	mov eax, p_fila
	mov p_columna, eax						; p_columna = p_fila
	
inicializar_para_cada_columna:

	mov edi, ancho_instancia				; edi = contador de columna
	
	cmp dword orientacion, 0
	je optimizacion_para_atras				
	jmp optimizacion						
	
optimizacion_para_atras:

	mov eax, p_columna
	add eax, ancho_instancia_bytes
	sub eax, 16
	mov p_columna, eax
	mov ecx, partes
	
ciclo_optimizacion_para_atras:

	mov eax, p_columna
	movdqu xmm7, [eax]
	psrldq xmm7, 1
	
primer_pixel_para_atras:

	movd eax, xmm7
	and eax, mascara_pixel
	movd xmm6, eax
	pslldq xmm6, bytes_por_pixel*4
	
segundo_pixel_para_atras:

	psrldq xmm7, bytes_por_pixel
	movd eax, xmm7
	and eax, mascara_pixel
	movd xmm5, eax
	pslldq xmm5, bytes_por_pixel*3
	por xmm6, xmm5
	
tercer_pixel_para_atras:

	psrldq xmm7, bytes_por_pixel
	movd eax, xmm7
	and eax, mascara_pixel
	movd xmm5, eax
	pslldq xmm5, bytes_por_pixel*2
	por xmm6, xmm5
	
cuarto_pixel_para_atras:

	psrldq xmm7, bytes_por_pixel
	movd eax, xmm7
	and eax, mascara_pixel
	movd xmm5, eax
	pslldq xmm5, bytes_por_pixel
	por xmm6, xmm5
	
quinto_pixel_para_atras:

	psrldq xmm7, bytes_por_pixel
	movd eax, xmm7
	and eax, mascara_pixel
	movd xmm5, eax
	por xmm6, xmm5
	
guardar_pixeles_para_atras:

	mov eax, p_instancia
	movdqu [eax], xmm6
	
	sub edi, pixeles_completos_en_128_bits
	
	add eax, bytes_en_5_pixeles
	mov p_instancia, eax
	
	mov eax, p_columna
	sub eax, bytes_en_5_pixeles
	mov p_columna, eax
	
	dec ecx
	cmp ecx, 0
	je fin_optimizacion_para_atras
	jmp ciclo_optimizacion_para_atras
	
fin_optimizacion_para_atras:

	mov eax, p_columna
	add eax, bytes_en_5_pixeles - 2
	mov p_columna, eax
	jmp para_cada_columna
	
optimizacion:

	mov ecx, partes
	
ciclo_optimizacion:

	mov eax, p_columna
	movdqu xmm0, [eax]
	
	mov ebx, p_instancia
	movdqu [ebx], xmm0

	sub edi, pixeles_completos_en_128_bits
	
	add eax, bytes_en_5_pixeles
	mov p_columna, eax
	
	add ebx, bytes_en_5_pixeles
	mov p_instancia, ebx
	
	loop ciclo_optimizacion
	
para_cada_columna:

	cmp edi, 0
	je siguiente_fila						; si edi = 0 voy a la siguiente fila
	
	mov eax, p_columna
	mov ebx, p_instancia
	mov eax, [eax]
	mov dword [ebx], eax
	
siguiente_columna:
	
	mov eax, p_instancia
	add eax, bytes_por_pixel
	mov p_instancia, eax					; avanzo puntero instancia un pixel
	
	mov eax, p_columna
	add eax, bytes_por_pixel
	mov p_columna, eax						; avanzo puntero columna un pixel
	
	dec edi
	
	cmp dword orientacion, 0
	je volver_columna_atras					; si no hay que dar vuelta la imagen empiezo
	jmp para_cada_columna
	
volver_columna_atras:

	mov eax, p_columna
	sub eax, 6
	mov p_columna, eax						; p_columna-= 6
	jmp para_cada_columna
	
siguiente_fila:
	
	dec esi
	
	mov eax, ancho_sprite_bytes
	add p_fila, eax							; p_fila+= ancho_sprite_bytes
	
	mov eax, resto_ancho_instancia_bytes
	cmp eax, 0
	je para_cada_fila
	
	mov ebx, 4
	sub ebx, eax
	add p_instancia, ebx
	
	jmp para_cada_fila

fin:

	pop esi									; desarmo el stack frame
	pop edi									; desarmo el stack frame
	pop ebx									; desarmo el stack frame
	add esp, bytes_reservados				; desarmo el stack frame
	pop ebp									; desarmo el stack frame

	ret
